<?php
/**
 *
 * 모델 최상위 클래스
 *
 */

class coreModel
{
    // DB instance
    public $dbInstance = null;
    // DB id
    protected $db = '';
    protected $interface = SC_DB_INTERFACE;
    //protected $interface = 'PDO';
    protected $result = null;

    public $debugging = null;
    public $debug = false;
    public $debugType = 'win';

    // 쿼리 로그
    protected $aLog = array();


    public function __construct($db, $type = 'factory', $options = array())
    {
        global $DEBUG_INFO;

        if (empty($db)) return false;

        $this->db = $db;

        if (empty($GLOBALS['DATABASE_INSTANCE'][$db]) === true) {
            
            // DB instance 세팅
            if ($this->interface == 'MDB2') {
                $this->dbInstance = commDb::getInstance($db, $type, $options);
            } else if ($this->interface == 'PDO') {
                $this->dbInstance = commDbp::getInstance();
            }
            
            // DB instance 저장
            $GLOBALS['DATABASE_INSTANCE'][$db] = $this->dbInstance;

        } else {
            // DB instance 조회
            $this->dbInstance = $GLOBALS['DATABASE_INSTANCE'][$db];
        }

        // model debugging instance
        $this->debugging = new utilDebugModel($this->debug, $this->debugType, get_class($this));
    }

    public function executeQuery($sql, $type = 'rows', $param = array())
    {
        $this->aLog = array();

        $this->debugging->start();

        // 쿼리 로그 저장
        $this->aLog[] = $sql;
        
        if ($this->interface == 'MDB2') {
            //$rows = $this->_executeQuery($sql, $type, $isCache, $cacheOption);
            $rows = $this->_executeQuery($sql, $type, $aParam);
            
        } else if ($this->interface == 'PDO') {
            $rows = $this->dbInstance->autoExecute($sql, $type, $param);
        }
        
        $this->aLog[] = 'Model ::: '.get_class($this);
        $this->debugging->setLog($this->aLog);

        return $rows;
    }

    //private function _executeQuery($sql, $type, $isCache, $cacheOption)
    private function _executeQuery($sql, $type, $aParam)
    {
        $type = $this->exec($sql, $type, $aParam);

        if ($this->isDbConnected()) {
            if ($type == 'exec') {
                if (DEBUG && ($this->result === false)) {
                    $this->getErrorMessage();
                    $_message = implode('<br />', $this->aLog);
                    throw new exceptionDb($_message);
                }

                return $this->result;
            }
        }

        if ($this->interface == 'MDB2' && $this->result->code < 0 && DEBUG) {
            $this->aLog[] = $this->result->message;
            $this->aLog[] = $this->result->useinfo;
            $_message = implode('<br />', $this->aLog);
            throw new exceptionDb($_message);
        }

        if (empty($this->result)) {
            if (DEBUG) {
                $this->getErrorMessage();
                $_message = implode('<br />', $this->aLog);
                throw new exceptionDb($_message);
            }
        }

        $rows = $this->getResult($type);

        // 메모리 반환
        // todo
        // cache 가 필요할 경우 재정의
        if (isset($this->result)) {
            $this->result->free();
        }

        return $rows;
    }

    //private function exec($sql, $type)
    private function exec($sql, $type, $aParam)
    {
        if ($this->dbInstance->dsn['phptype'] == 'pgsql') {

        }

        // select
        if ($this->isSelect(trim($sql)) === 0) {
            $this->result = $this->dbInstance->query($sql);

        } else {
            $this->result = $this->dbInstance->exec($sql);
            $type = 'exec';
        }

        return $type;
    }

    /**
     *
     * select 문인지 확인
     * @param string $sql 쿼리
     */
    private function isSelect($sql)
    {
        return stripos($sql, 'select');
    }

    /**
     *
     * DB connection 정상 여부 확인
     */
    private function isDbConnected()
    {
        if ($this->interface == 'PDO') {
            return isset($this->dbInstance) ? true : false;

        } else {
            return $this->dbInstance->code != -4 ? true : false;
        }
    }

    /**
     *
     * 에러 메시지 기록
     */
    private function getErrorMessage()
    {
        if ($this->interface == 'PDO') {
            $aErrorInfo = $this->dbInstance->errorInfo();
            $this->aLog[] = $aErrorInfo[2];

            //return $aErrorInfo[2];

        } else {
            $this->aLog[] = $this->dbInstance->message;
            $this->aLog[] = $this->dbInstance->userinfo;

            //return $this->db->message.' '.$this->db->userinfo;
        }
    }

    private function getResult($type)
    {
        if ($this->isRows($type)) {
            return $this->getRows();

        } else if ($this->isRow($type)) {
            return $this->getRow();

        } else if ($type == 'exec') {
            return $this->result;
        }
    }

    private function isRows($type)
    {
        return ($type == 'rows') ? true : false;
    }

    private function isRow($type)
    {
        return ($type == 'row') ? true : false;
    }

    private function getRows()
    {
        $rows = array();

        while ($row = $this->getRow()) {
            $rows[] = $row;
        }

        return $rows;
    }

    private function getRow()
    {
        if (!$this->result) return;

        $row = ($this->interface == 'PDO') ? $this->result->fetch(PDO::FETCH_ASSOC) : $this->result->fetchRow(MDB2_FETCHMODE_ASSOC);

        return $row;
    }

    /**
     *
     * last insert id 조회
     * @param string $sTable
     * @param string $field
     */
    public function lastInsertID($sTable = null, $field = null)
    {
        if ($this->interface == 'MDB2') {
            return $this->dbInstance->lastInsertId($sTable, $field);

        } else {
            return $this->dbInstance->lastInsertId($sTable);
        }
    }

    /*
    public function disconnect()
    {
        foreach ($GLOBALS['DATABASE_INSTANCE'] as $key => $_db) {
            $_db->disconnect();
        }
    }
    */
}